home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 126-150 / disk_149 / less / src / print.c < prev    next >
C/C++ Source or Header  |  1992-05-06  |  10KB  |  493 lines

  1. /* print.c
  2.  
  3.  
  4.     simple print file utility for less by: Bob Leivian
  5.  
  6.     print -nh^ld#99|99t9wp:<string> file1 {-nh...}file2 file3 ...
  7.  
  8.     this is designed to be called from the less with the
  9.     expanded list of files to print with a option list
  10. */
  11.  
  12. #include <stdio.h>
  13. #include <ctype.h>
  14. long Open();
  15. #define MODE_OLDFILE 1005L
  16. #define MODE_NEWFILE 1006L
  17. long std_out;
  18. extern char prog_name[];
  19.  
  20. /* this can be set with options */
  21. int numbers = 0;
  22. int headers = 0;
  23. int control = 0;
  24. int prefix = 0;
  25. int lines_per_page = 0;
  26. int chars_per_line = 0;
  27. int tab_stops = 0;
  28.  
  29. long printer = 0;
  30.  
  31.  
  32. start_print(my_argc, my_argv)
  33. int my_argc;
  34. char *my_argv[];
  35. {
  36.     int i;
  37.     char *p;
  38.     char name[30];
  39.     char theprefix [30];
  40.     char c;
  41.  
  42.     if (printer == 0) {
  43.         printer = Open("PRT:", MODE_NEWFILE);
  44.         if (!printer) exit(27);
  45.     }
  46.  
  47.     while (my_argv[1]) {
  48.         /* process options if any */
  49.         while (*my_argv[1] == '-') {
  50.             p = (char *) &*my_argv[1];
  51.  
  52.             p++;        /* point to the option chars */
  53.             do {
  54.                 switch (*p) {
  55.                 case ' ':
  56.                 case '\0':        /* ignore nulls and spaces */
  57.                     break;
  58.  
  59.                 case 'p': case 'P':        /* turn on proportional mode */
  60.                     Write(printer, "\x1b[2p", 3L);
  61.                     break;
  62.  
  63.                 case 'c': case 'C':        /* turn on compressed mode */
  64.                     Write(printer, "\x1b[4w", 4L);
  65.                     break;
  66.  
  67.                 case 'u': case 'U':        /* turn on uncompressed  mode */
  68.                     Write(printer, "\x1b[3w", 4L);
  69.                     break;
  70.  
  71.                 case 'l': case 'L':        /* turn on letter quality mode */
  72.                     Write(printer, "\x1b[2\"z", 5L);
  73.                     break;
  74.  
  75.                 case 'd': case 'D':        /* turn on draft mode */
  76.                     Write(printer, "\x1b[1\"z", 5L);
  77.                     break;
  78.  
  79.                 case ':':        /* print control string first */
  80.                     strcpy(theprefix, ++p);
  81.                     prefix++;
  82.                     goto next; /* consume rest of option */
  83.  
  84.                 case '^':        /* print control chars as ^X */
  85.                     control++;
  86.                     break;
  87.  
  88.                 case 't': case 'T':        /* set tab stops */
  89.                     p++;
  90.                     if (isdigit(*p)) 
  91.                         tab_stops = *p - '0';
  92.                     else {
  93.                         tab_stops = 8;
  94.                         p--;
  95.                     }
  96.                     break;
  97.  
  98.                 case '#':                /* set lines per page */
  99.                     p++;
  100.                     lines_per_page = 0;
  101.                     while(isdigit(*p)) {
  102.                         lines_per_page *= 10;
  103.                         lines_per_page += (*p++ - '0');
  104.                     }
  105.                     p--;
  106.                     break;
  107.  
  108.                 case '|':                /* set chars per line */
  109.                     p++;
  110.                     chars_per_line = 0;
  111.                     while(isdigit(*p)) {
  112.                         chars_per_line *= 10;
  113.                         chars_per_line += (*p++ - '0');
  114.                     }
  115.                     p--;
  116.                     break;
  117.  
  118.                 case 'n': case 'N':        /* print line numbers */
  119.                     numbers++;
  120.                     break;
  121.  
  122.                 case 'h':        /* print a header */
  123.                     headers++;
  124.                     break;
  125.  
  126.                 default:
  127.                     /* ignore invalid stuff for now */;
  128.                 }
  129.                 p++; 
  130.             } while (*p);
  131.     next:
  132.             my_argc--;
  133.             my_argv++;
  134.         }
  135.  
  136.         /* put out the control prefix if any */
  137.         if (prefix) {
  138.             p = theprefix;
  139.             while(*p) {
  140.                 if (*p == '^') { 
  141.                     p++;
  142.                     c = *p - '@';
  143.                     Write(printer, &c, 1L);
  144.                 } else
  145.                     Write(printer, *p, 1L);
  146.                 p++;
  147.             }
  148.  
  149.             /* reset the prefix flag */
  150.             prefix = 0;
  151.         }
  152.  
  153.         /* now print the file */
  154.         print_one_file(my_argv[1]);
  155.         my_argv++;
  156.     }
  157.     Close(printer);
  158.     printer = 0;
  159. }
  160.  
  161. static char buf[1024];            /* Note! if called from WB we have */
  162. static char outbuf[1024+100];    /*  very limited stack space       */
  163.  
  164. /* do the actual print for a file */
  165. print_one_file(name)
  166. char *name;
  167. {
  168.     long in;
  169.     long bytes, Read();
  170.  
  171.     register long outbytes;
  172.     register char *p;
  173.  
  174.     int line;
  175.     int page;
  176.     int num_lines;
  177.     int new_line;
  178.     int chars;
  179.  
  180.     char line_buf[10];
  181.     char ctl[4];
  182.     int i;
  183.  
  184.     in = Open(name, MODE_OLDFILE);
  185.  
  186.     if (!in) {
  187.         sprintf(buf, "unable to open: '%s'\f", name);
  188.         Write(printer, buf, (long) strlen(buf));
  189.         return;
  190.     }
  191.  
  192.     line = 1;
  193.     page = 1;
  194.  
  195.     /* print a file header if desired */
  196.     if (headers) {
  197.         sprintf(buf, "File: %s    Page %d\n\n", name, page);
  198.         Write(printer, buf, (long) strlen(buf));
  199.         num_lines = 3;
  200.     } else
  201.         num_lines = 1;
  202.  
  203.     if (numbers || control || lines_per_page || chars_per_line) {
  204.  
  205.         outbytes = 0;
  206.         if (numbers) {
  207.             sprintf(outbuf, "%4d ", line);
  208.             outbytes = strlen(outbuf);
  209.             chars = outbytes;
  210.         }
  211.  
  212.         /* now read the file a block at a time */
  213.         while(bytes = Read(in, buf, 1024L)) {
  214.             p = buf;
  215.             if (bytes < 0) {
  216.                 sprintf(buf, "Error reading file: %s\n", name);
  217.                 Write(printer, buf, (long) sizeof(buf));
  218.                 return;
  219.             }
  220.  
  221.             /* now write out this block */
  222.             while(bytes) {
  223.                 /* check for control chars, if requested */
  224.                 if (control) {
  225.                     if ((*p < ' ')&&(*p != '\n')&&(*p != '\t')){
  226.                         /* print all other control chars in ^A format */
  227.                         outbuf[outbytes++] = '^';
  228.                         *p += '@';
  229.                         chars++;
  230.                     }
  231.                 }
  232.  
  233.                 /* check for a new line */
  234.                 if ((*p == '\n')||(*p == '\f')) {
  235.                     /* newline, need a page break? */
  236.                     if (((*p == '\f') && (!control)) ||
  237.                         (lines_per_page && (num_lines >= lines_per_page))) {
  238.  
  239.                         /* is this a user formfeed */
  240.                         if (*p == '\f') {
  241.                             sprintf(buf, "<form feed>\f");
  242.                             strcpy(&outbuf[outbytes], buf);
  243.                             outbytes += strlen(buf);
  244.                             line--;
  245.                         } else
  246.                             outbuf[outbytes++] = '\f';
  247.  
  248.                         /* print a file header if desired */
  249.                         page++;
  250.                         if (headers) {
  251.                             sprintf(buf, "File: %s    Page %d\n\n",
  252.                                     name, page);
  253.                             strcpy(&outbuf[outbytes], buf);
  254.                             outbytes += strlen(buf);
  255.                             num_lines = 2;
  256.                         } else
  257.                             num_lines = 0;
  258.                     }
  259.                     line++;
  260.                     num_lines++;
  261.                     new_line = 1;
  262.                 } else
  263.                     new_line = 0;
  264.  
  265.                 /* now put the character and account for it */
  266.                 chars++;
  267.                 bytes--;
  268.                 switch (*p) {
  269.                 case '\t':
  270.                     if (tab_stops) {
  271.                         if ((chars % tab_stops) == 0) {
  272.                             for(i=0; i < tab_stops; i++) {
  273.                                 outbuf[outbytes++] = ' ';
  274.                                 chars++;
  275.                             }
  276.                         } else 
  277.                             while(chars % tab_stops) {
  278.                                 outbuf[outbytes++] = ' ';
  279.                                 chars++;
  280.                             }
  281.                         p++;
  282.                     } else {
  283.                         while(chars % 8) chars++;
  284.                         outbuf[outbytes++] = *p++;
  285.                     }
  286.                     break;
  287.  
  288.                 case '\f':    /* formfeeds are accounted for eariler */
  289.                     p++;
  290.                     break;
  291.  
  292.                 case 8:
  293.                     chars--;
  294.                     outbuf[outbytes++] = *p++;
  295.                     break;
  296.  
  297.                 default:
  298.                     outbuf[outbytes++] = *p++;
  299.                 }
  300.  
  301.                 /* check for line overflow, if requested */
  302.                 if (chars_per_line && (chars >= chars_per_line)) {
  303.                     outbuf[outbytes++] = '\n';
  304.                     num_lines++;
  305.                     if (numbers) {
  306.                         strcpy(&outbuf[outbytes], "     ");
  307.                         outbytes += 5;
  308.                         chars = 5;
  309.                     } else
  310.                         chars = 0;
  311.                 }
  312.  
  313.                 /* now put out the line number if needed */
  314.                 if (new_line && numbers) {
  315.                     sprintf(&outbuf[outbytes], "%4d ", line);
  316.                     outbytes += 5;
  317.                     chars = 5;
  318.                 }
  319.  
  320.                 /* dump the buffer if near full */
  321.                 if (outbytes >= 1000L) {
  322.                     Write(printer, outbuf, outbytes);
  323.                     outbytes = 0;
  324.                 }
  325.             } /* while chars in this block */
  326.         } /* while not EOF */
  327.  
  328.         /* flush last line */
  329.         if (outbytes) 
  330.             Write(printer, outbuf, outbytes);
  331.     } else {
  332.         /* we can just pump out the data untouched */
  333.         while(bytes = Read(in, buf, 1024L))
  334.             if (bytes > 0)
  335.                 Write(printer, buf, bytes);
  336.             else {
  337.                 sprintf(buf, "Error reading file");
  338.                 Write(printer, buf, (long) sizeof(buf));
  339.             }
  340.  
  341.     }
  342.     Write(printer, "\f", 1L);
  343.     Close(in);
  344.     in = 0;
  345. }
  346.  
  347. set_up_print(name)
  348. char *name;
  349. {
  350.     long save;
  351.     extern long tty;
  352.     extern char **av;
  353.     extern int called_from_WB;
  354.     extern long current_dir;
  355.     char option_string[80];
  356.     char numbuf[16];
  357.     char c;
  358.     int i;
  359.     char buf[100];
  360.     long result, Execute();
  361.     int fake_argc;
  362.     char *fake_argv[4];
  363.  
  364.    /* 
  365.     * print the current file
  366.     */
  367.  
  368.     save = tty;
  369.  
  370.     /* first make sure we can get the printer */
  371.     printer = Open("PRT:", MODE_NEWFILE);
  372.     if (!printer) {
  373.         error("can't access the printer at this time");
  374.     } else {
  375.  
  376.         /* printer is avail so... */
  377.         tty = Open("RAW:100/50/470/100/Less's print server", MODE_NEWFILE);
  378.         if (!tty) {
  379.              tty = save;
  380.             Close(printer);
  381.             printer = 0;
  382.             error("Can't open window!");
  383.             return;
  384.         }
  385.  
  386.         ttputs("Print File: ");
  387.         ttputs(name);
  388.         ttputs("\nEnter the first letter of each option, if any\n");
  389.         ttputs("For example 'nh#60|80t8^l', the options are...\n");
  390.         so_enter();
  391.         ttputs("numberedlines headers ^ctrl proportional         \n");
  392.         ttputs("letterquality draft wide uncompressed            \n");
  393.         ttputs("#<num> of rows, |<num> of columns, t<num> tabstop\n");
  394.         so_exit();
  395.         ttputs("\nOptions or 'q' to quit? ");
  396.  
  397.         /* get a responce */
  398.         i = 0;
  399.         while (c = ttgetc()) {
  400.             if (c == 8) { /* backspace ? */
  401.                 if (i > 0) {
  402.                     i--;
  403.                     ttputc(c);
  404.                 }
  405.             } else {
  406.                 if ((c < ' ') || (i > 32)) break;
  407.                 option_string[i++] = c;
  408.                 ttputc(c);
  409.             }
  410.         }
  411.         option_string[i] = 0;
  412.  
  413.         if(toupper(option_string[0]) != 'Q') {
  414.  
  415.             if (called_from_WB) {
  416. /* I haven't figured out how to queue from WB */
  417. #ifndef WB_QUEUED
  418.                 if (option_string[0]) {
  419.                     sprintf(buf, "-%s", option_string);
  420.                     fake_argc = 3;
  421.                     fake_argv[1] = buf;
  422.                     fake_argv[2] = name;
  423.                 } else {
  424.                     fake_argc = 2;
  425.                     fake_argv[1] = name;
  426.                 }
  427.                 fake_argv[fake_argc] = NULL;
  428.  
  429.                 ttputs("\nPrinting...\n");
  430.                 start_print(fake_argc, fake_argv);
  431.                 ttputs("Complete!\n");
  432. #else
  433.                 /* this should work but I can't figure out why not */
  434.                 sprintf(buf, "RUN %s -p %ld ", prog_name, current_dir); 
  435.  
  436.                 if (option_string[0]) {
  437.                     strcat(buf, "-");
  438.                     strcat(buf, option_string);
  439.                     strcat(buf, " ");
  440.                 }
  441.                 strcat(buf, name);
  442.  
  443.                 /* give up the printer */
  444.                 Close(printer);
  445.                 printer = 0;
  446.  
  447.                 /* and execute the job */
  448.                 std_out = Open("NIL:", MODE_OLDFILE);
  449.                 result = Execute(buf, 0L, std_out);
  450.                 if (result) {
  451.                     ttputs("\nJob queued\n");
  452.                 } else {
  453.                     sprintf(buf, "\nError on Execute: %ld", result);
  454.                     ttputs(buf);
  455.                 }
  456. #endif
  457.             } else {
  458.                 /* from CLI, queue it  to a copy of myself */
  459.                 sprintf(buf, "RUN %s -p ", prog_name); 
  460.  
  461.                 if (option_string[0]) {
  462.                     strcat(buf, "-");
  463.                     strcat(buf, option_string);
  464.                     strcat(buf, " ");
  465.                 }
  466.                 strcat(buf, name);
  467.  
  468.                 /* give up the printer */
  469.                 Close(printer);
  470.                 printer = 0;
  471.  
  472.                 /* and execute the job */
  473.                 result = Execute(buf, 0L, 0L);
  474.                 if (result) {
  475.                     ttputs("\nJob queued\n");
  476.                 } else {
  477.                     sprintf(buf, "\nError on Execute: %ld", result);
  478.                     ttputs(buf);
  479.                 }
  480.             }
  481.         } else {
  482.             Close(printer);
  483.             printer = 0;
  484.             ttputs("\nPrint request canceled by user!\n");
  485.         }
  486.  
  487.         Delay(100L);
  488.         ttclose();
  489.         tty = save;
  490.     }
  491. }
  492.  
  493.